package com.my.json.sensitive.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.my.json.sensitive.annotation.SensitiveField;
import com.my.json.sensitive.enums.SensitiveType;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Objects;

/**
 * @author hexinglin
 * @created 2021-12-29 15:48
 **/
public class SensitiveInfoSerialize extends JsonSerializer<String> implements ContextualSerializer {
    private static final Logger logger = LoggerFactory.getLogger(SensitiveInfoSerialize.class);
    private static CompositeSensitiveHandler handler = new CompositeSensitiveHandler();
    private SensitiveField sensitiveField;

    public SensitiveInfoSerialize() {
    }

    public SensitiveInfoSerialize(SensitiveField sensitiveField) {
        this.sensitiveField = sensitiveField;
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        if (property != null) {
            if (Objects.equals(property.getType().getRawClass(), String.class)) {
                SensitiveField sensitiveField = (SensitiveField)property.getAnnotation(SensitiveField.class);
                if (sensitiveField == null) {
                    sensitiveField = (SensitiveField)property.getContextAnnotation(SensitiveField.class);
                }

                if (sensitiveField != null) {
                    return new SensitiveInfoSerialize(sensitiveField);
                }
            } else {
                logger.debug("未对字段进行序列化，因为数据类型非String");
            }

            return prov.findValueSerializer(property.getType(), property);
        } else {
            return prov.findNullValueSerializer(property);
        }
    }

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        SensitiveType type = this.sensitiveField.type();
        if (!SensitiveType.NULL.equals(type)) {
            String ret = handler.sensitive(value, type);
            gen.writeString(ret);
        } else {
            gen.writeString(this.split(value));
        }

    }

    private String split(String text) {
        if (StringUtils.isBlank(text)) {
            return "";
        } else {
            int length = text.length();
            if (this.sensitiveField.prefix() + this.sensitiveField.suffix() >= length) {
                return text;
            } else {
                String left = StringUtils.left(text, this.sensitiveField.prefix());
                String right = StringUtils.right(text, this.sensitiveField.suffix());
                length = this.sensitiveField.suffix() + this.sensitiveField.split();
                return left.concat(StringUtils.leftPad(right, length, '*'));
            }
        }
    }
}
